#pragma once
#include "VulkanApplication.h"

struct Vertex
{
    float x, y, z;
    float r, g, b;
    float u, v;
};

class BufferManager
{
public:
    BufferManager(VulkanApplication* app);
    ~BufferManager();

    bool createDescriptorSet();
    bool prepare(const std::string& vertFile, const std::string& fragFile);
    void cleanup();

    VkBuffer createVertexBuffer(const std::string& name, const std::vector<Vertex>& vertices);
    VkBuffer createIndexBuffer(const std::string& name, const std::vector<unsigned int>& indices);
    VkBuffer createUniformBuffer(const std::string& name, size_t uboSize);

    VkImage createTextureImage(const std::string& name, const std::string& filename);
    VkSampler createTextureSampler(const std::string& name, VkImage image, VkFormat format);
    void updateTextureDescriptor(const std::string& name, VkImageLayout layout);

    bool createBuffer(VkBuffer& buffer, size_t dataSize, VkBufferUsageFlags usage);
    bool createBufferMemory(VkDeviceMemory& bufferMemory,
                            VkMemoryRequirements& memRequirements, uint32_t propertyBits);
    VkBuffer getBuffer(const std::string& name);
    VkImageView getImageView(const std::string& name);

    void* mapBufferMemory(const std::string& name, size_t dataSize);
    void unmapBufferMemory(const std::string& name);

    VkDescriptorSetLayout getDescriptorSetLayout() { return _descriptorSetLayout; }
    VkDescriptorSet getDescriptorSet() { return _descriptorSet; }

private:
    std::map<std::string, VkBuffer> _bufferMap;
    std::map<std::string, VkDeviceMemory> _bufferMemoryMap;
    std::map<std::string, VkImage> _imageMap;
    std::map<std::string, VkImageView> _imageViewMap;
    std::map<std::string, VkSampler> _imageSamplerMap;

    VkDescriptorPool _descriptorPool;
    VkDescriptorSetLayout _descriptorSetLayout;
    VkDescriptorSet _descriptorSet;
    VulkanApplication* _application;
};
